﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace TrainTicketsAuto.Ocrlib
{
    internal class PicProcess
    {
        //private static char a(c[] A_0)
        //{
        //    int index = 0;
        //    int num2 = 10000;
        //    for (int i = 0; i < A_0.Length; i++)
        //    {
        //        if (num2 > A_0[i].f())
        //        {
        //            num2 = A_0[i].f();
        //            index = i;
        //        }
        //    }
        //    return A_0[index].b();
        //}

        //private static Bitmap GrayByPixelsFromArray(int[,] picArray)
        //{
        //    Bitmap bitmap = new Bitmap(picArray.GetLength(1), picArray.GetLength(0));
        //    for (int i = 0; i < picArray.GetLength(0); i++)
        //    {
        //        for (int j = 0; j < picArray.GetLength(1); j++)
        //        {
        //            if (picArray[i, j] == 0)
        //            {
        //                picArray[i, j] = 255;
        //            }
        //            else
        //            {
        //                picArray[i, j] = 0;
        //            }
        //            bitmap.SetPixel(j, i, Color.FromArgb(picArray[i, j], picArray[i, j], picArray[i, j]));
        //        }
        //    }
        //    return bitmap;
        //}

        /// <summary>
        /// For current 12306 Verification code （only 4 chars）
        /// </summary>
        /// <param name="A_0"></param>
        /// <returns></returns>
        private static string GetMatchedFourChars(List<Character> A_0)
        {
            StringBuilder builder = new StringBuilder();
            A_0.Sort();
            SortedList list = new SortedList();
            for (int i = 0; i < 4; i++)
            {
                if (A_0.Count < 4)
                {
                    return "";
                }
                list.Add(A_0[i].d(), A_0[i]);
                for (int j = i + 1; j < A_0.Count; j++)
                {
                    if (Math.Abs((int) (A_0[i].d() - A_0[j].d())) < 3)
                    {
                        if (((Character) list[A_0[i].d()]).a() < A_0[j].a())
                        {
                            list[A_0[i].d()] = A_0[j];
                        }
                        A_0.RemoveAt(j);
                        j--;
                    }
                }
            }
            foreach (DictionaryEntry entry in list)
            {
                builder.Append(((Character) entry.Value).b());
            }
            return builder.ToString();
        }

        private static int[,] GrayByPixelsToArray(Bitmap pic)
        {
            int[,] picArray = new int[pic.Height,pic.Width];
            for (int i = 0; i < pic.Height; i++)
            {
                for (int j = 0; j < pic.Width; j++)
                {
                    if (170 < GetGrayNumColor(pic.GetPixel(j, i)))
                    {
                        picArray[i, j] = 0;
                    }
                    else
                    {
                        picArray[i, j] = 1;
                    }
                }
            }
            return picArray;
        }

        private static int GetGrayNumColor(Color posClr)
        {
            return ((((posClr.R*19595) + (posClr.G*38469)) + (posClr.B*7472)) >> 16);
        }

        private static int a(uint A_0)
        {
            int num = 0;
            while (num < A_0)
            {
                num++;
                A_0 &= A_0 - 1;
            }
            return num;
        }

        private static List<Character> GetCharacterList(CharPicPixels A_0, CharPicPixels[] A_1)
        {
            List<Character> list = new List<Character>();
            for (int i = 0; i < A_1.Length; i++)
            {
                for (int j = 0; j <= (A_0.c1() - 1); j++)
                {
                    int num3 = A_0.c1() - ((A_1[i].c1()/2) + j);
                    for (int k = 0; k <= A_0.d(); k++)
                    {
                        int num5 = k - (A_1[i].d()/2);
                        if (num5 < 0)
                        {
                            num5 = 0;
                        }
                        int num6 = ((A_1[i].d() + 1)/2) + k;
                        if (num6 > A_0.d())
                        {
                            num6 = A_0.d();
                        }
                        int num8 = 0;
                        int num9 = 0;
                        int num7 = num5;
                        while (num7 < num6)
                        {
                            uint num10;
                            int num11 = (((A_1[i].d()/2) - k) > 0) ? ((A_1[i].d()/2) - k) : 0;
                            if (num3 > 0)
                            {
                                num10 = A_1[i].a()[(num11 + num7) - num5] << (num3 & 0x1f);
                            }
                            else
                            {
                                num10 = A_1[i].a()[(num11 + num7) - num5] >> ((num3*-1) & 0x1f);
                            }
                            num10 &= ((uint) Math.Pow(2.0, (double) A_0.c1())) - 1;
                            num8 += a(num10);
                            if (num8 == 0)
                            {
                                num9++;
                            }
                            if (((num10 & A_0.a()[num7]) ^ num10) != 0)
                            {
                                break;
                            }
                            num7++;
                        }
                        if ((num7 == num6) && (num8 != 0))
                        {
                            if (num3 > 0)
                            {
                                if ((A_1[i].c1() + num3) < A_0.c1())
                                {
                                    A_1[i].c1();
                                }
                                else
                                {
                                    A_0.c1();
                                }
                            }
                            else
                            {
                                A_1[i].c1();
                            }
                            Character item = new Character(A_1[i].b(), num5 + num9, ((float) num8)/((float) A_1[i].g()),
                                                           A_1[i].g());
                            list.Add(item);
                        }
                    }
                }
            }
            return list;
        }

        public static string GetTextFromPic(Bitmap pic)
        {
            CharPicPixels c = new CharPicPixels(GrayByPixelsToArray(pic));
            CharPicPixels[] cArray = CharPicPixelsInit.a();
            List<Character> CharacterLists = GetCharacterList(c, cArray);
            return GetMatchedFourChars(CharacterLists);
        }
    }
}
